﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace XinKuaiJiInterface
{
    public static class Util
    {
        private static readonly string sign = "xinkuaijicomeon";//签名密码
        private static readonly string key = "jpdxmd*@";//对称密钥，只能为8位
        private static readonly bool isCheckSign = false;//是否校验签名密码
        private static readonly bool isEncrypt = false;//是否对url参数进行加密

        /// <summary>
        ///客户端参数依次拼接后，加上签名密码，进行mdb5加密，此生成服务端校验码 
        /// </summary>
        /// <param name="clientUrlParam">客户端参数</param>
        /// <returns>服务端校验码</returns>
        public static string buildServerSign(List<string> clientUrlParam)
        {
            string clientParams = "";
            foreach (var item in clientUrlParam)
            {
                clientParams += item;
            }
            clientParams += sign;
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] fromData = md5.ComputeHash(Encoding.Default.GetBytes(clientParams));
            string serverSign = BitConverter.ToString(fromData).Replace("-", "");
            return serverSign;
        }
        /// <summary>
        /// 检查服务端校验码是否与客户端校验码一致
        /// </summary>
        /// <param name="clientUrlParam">客户端参数</param>
        /// <param name="sign">客户端校验码</param>
        /// <returns></returns>
        public static bool checkSignSuccess(List<string> clientUrlParam, string sign)
        {
            if (isCheckSign)//判断是否校验签名密码
            {
                String decryptSign = Util.UrlDecrypt(sign);//对客户端sign进行解密
                string serverSign = buildServerSign(clientUrlParam);
                if (serverSign != decryptSign)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 对url参数进行加密
        /// </summary>
        /// <param name="pToEncrypt">url参数</param>
        /// <param name="sKey">加密key</param>
        /// <returns>加密后的url参数</returns>
        public static string UrlEncrypt(string pToEncrypt)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
            des.Key = ASCIIEncoding.ASCII.GetBytes(key);
            des.IV = ASCIIEncoding.ASCII.GetBytes(key);
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                ret.AppendFormat("{0:X2}", b);
            }
            ret.ToString();
            ms.Close();
            return ret.ToString();
        }

        /// <summary>
        /// 对url参数进行解密
        /// </summary>
        /// <param name="pToEncrypt">加密后的url参数</param>
        /// <param name="sKey">加密key</param>
        /// <returns>解密后的url参数</returns>
        public static string UrlDecrypt(string pToDecrypt)
        {
            if (isEncrypt)//是否对url参数进行加密
            {
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
                for (int x = 0; x < pToDecrypt.Length / 2; x++)
                {
                    int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
                    inputByteArray[x] = (byte)i;
                }

                des.Key = ASCIIEncoding.ASCII.GetBytes(key);
                des.IV = ASCIIEncoding.ASCII.GetBytes(key);
                using (MemoryStream ms = new MemoryStream())
                {
                    CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    StringBuilder ret = new StringBuilder();
                    return System.Text.Encoding.Default.GetString(ms.ToArray());
                }   
            }
            return pToDecrypt;
        }
        public static string getJsonByObject(Object obj)
        {
            //实例化DataContractJsonSerializer对象，需要待序列化的对象类型
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
            //实例化一个内存流，用于存放序列化后的数据
            MemoryStream stream = new MemoryStream();
            //使用WriteObjcet序列化对象
            serializer.WriteObject(stream, obj);
            //写入内存流
            byte[] dataBytes = new byte[stream.Length];
            stream.Position = 0;
            stream.Read(dataBytes, 0, (int)stream.Length);
            //通过utf8格式转换为字符串
            return Encoding.UTF8.GetString(dataBytes);
        }
        public static Object getObjectByJson(string jsonString,Object obj)
        {
            //实例化DataContractJsonSerializer对象，需要待序列化的对象类型
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
            //把json传入内存流中保存
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
            {
                //使用ReadObject方法反序列化对象
                return serializer.ReadObject(stream);
            }
        }

        /// <summary>
        /// 输出日志到Log4Net
        /// </summary>
        /// <param name="t"></param>
        /// <param name="ex"></param>
        #region static void WriteLog(Type t, Exception ex)

        public static void WriteLog(Type t, Exception ex)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(t);
            log.Error("Error", ex);
        }

        #endregion

        /// <summary>
        /// 输出日志到Log4Net
        /// </summary>
        /// <param name="t"></param>
        /// <param name="msg"></param>
        #region static void WriteLog(Type t, string msg)

        public static void WriteLog(Type t, string msg)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(t);
            log.Error(msg);
        }

        #endregion

    }
}